package goffmpeg

import (
	"context"
	"fmt"
	"io"
	"time"

	"gitee.com/general252/goffmpeg/base"
	ffmpeg "gitee.com/general252/goffmpeg/golay"
)

type Packet struct {
	PTS         time.Duration
	DTS         time.Duration
	Data        []byte
	StreamIndex int
	Flags       int32
	FlagKEY     bool
	Duration    time.Duration
	Pos         int64
}

type Demuxer struct {
	cli      ffmpeg.FFmpegServiceClient
	filename string

	handle  int64
	context *ffmpeg.AVFormatContext
}

func NewDemuxer(filename string) *Demuxer {
	return &Demuxer{
		cli:      base.GetClient(),
		filename: filename,
	}
}

func (tis *Demuxer) Open() error {
	var (
		cli      = tis.cli
		filename = tis.filename
	)

	resp, _ := cli.DemuxerOpen(context.TODO(), &ffmpeg.DemuxerOpenRequest{Url: filename})
	if resp.GetCode() != ffmpeg.ResultCode_CodeOK {
		return fmt.Errorf("%v", resp.GetMsg())
	}

	tis.handle = resp.GetHandle()
	tis.context = resp.GetContext()

	return nil
}

func (tis *Demuxer) Close() {
	if tis.handle != 0 {
		_, _ = tis.cli.DemuxerClose(context.TODO(), &ffmpeg.DemuxerCloseRequest{Handle: tis.handle})
		tis.handle = 0
	}
}

func (tis *Demuxer) Duration() time.Duration {
	return time.Duration(tis.context.GetDuration()) * time.Microsecond
}

func (tis *Demuxer) ReadPacket() (*Packet, error) {
	cli := tis.cli

	resp, _ := cli.DemuxerReadPacket(context.TODO(), &ffmpeg.DemuxerReadPacketRequest{Handle: tis.handle})
	if resp.GetCode() != ffmpeg.ResultCode_CodeOK {
		if resp.GetCode() == ffmpeg.ResultCode_CodeEOF {
			return nil, io.EOF
		}
		return nil, fmt.Errorf("%v", resp.GetMsg())
	}

	pkt := resp.GetPacket()

	return &Packet{
		PTS:         time.Millisecond * time.Duration(pkt.GetPts()),
		DTS:         time.Millisecond * time.Duration(pkt.GetDts()),
		Data:        pkt.GetData(),
		StreamIndex: int(pkt.GetStreamIndex()),
		Flags:       pkt.GetFlags(),
		FlagKEY:     pkt.GetFlagKEY(),
		Duration:    time.Millisecond * time.Duration(pkt.GetDuration()),
		Pos:         pkt.GetPos(),
	}, nil
}
